# -*- coding: utf-8 -*-
import email
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from email import encoders
from email.header import Header
from email.mime.text import MIMEText
from email.utils import parseaddr, formataddr
import smtplib
import poplib
import re
import base64
import socket

# format addr
def _format_addr(s):
    name, addr = parseaddr(s)
    return formataddr((Header(name, 'utf-8').encode(),
                       addr.encode('utf-8') if isinstance(addr, unicode) else addr))


# to print the email in nature language
def print_info(msg, indent=0):
    '''
        print email in utf-8
    '''
    if indent == 0:
        # from to subject
        for header in ['From', 'To', 'Subject']:
            value = msg.get(header, '')
            if value:
                if header=='Subject':
                    value = decode_str(value)
                else:
                    hdr, addr = parseaddr(value)
                    name = decode_str(hdr)
                    value = u'%s <%s>' % (name, addr)
            print('%s%s: %s' % ('  ' * indent, header, value))
    if (msg.is_multipart()):
        # if email is a MIMEMultpart
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            print('%spart %s' % ('  ' * indent, n))
            print('%s--------------------' % ('  ' * indent))
            # print childs
            print_info(part, indent + 1)
    else:
        # else judge content_type
        content_type = msg.get_content_type()
        if content_type=='text/plain' or content_type=='text/html':
            # text or html
            content = msg.get_payload(decode=True)
            # get charset
            charset = guess_charset(msg)
            if charset:
                content = content.decode(charset)
            print('%sText: %s' % ('  ' * indent, content + '...'))
        else:
            # else have fujian
            print('%sAttachment: %s' % ('  ' * indent, content_type))

# to decode the string
def decode_str(s):
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value

# to guess charset
def guess_charset(msg):
    # get charset
    charset = msg.get_charset()
    if charset is None:
        # maybe content_type
        content_type = msg.get('Content-Type', '').lower()
        pos = content_type.find('charset=')
        if pos >= 0:
            charset = content_type[pos + 8:].strip()
    return charset

# api to send email use smtplib module
def send_email_with_lib(smtp_server, from_addr, to_addr, password, msg):
    server = smtplib.SMTP(smtp_server, 25)
    server.set_debuglevel(1)
    server.login(from_addr, password)
    server.sendmail(from_addr, [to_addr], msg.as_string())
    server.quit()

def send(clientSocket, msg):
    '''
        send msg & print receive use socket
    '''
    msg = b'%s\r\n' % msg
    clientSocket.send(msg)
    print ('send:', msg)
    recv = clientSocket.recv(1024).decode('utf-8')
    print 'recv:', recv
    return recv

def connect(server, port):
    '''
        connect to server use socket
    '''
    clientSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server = (server,port)
    clientSocket.connect(server)
    recv = clientSocket.recv(1024).decode('utf-8')
    print 'connect:',recv
    return clientSocket

def send_email(smtp_server, from_addr, to_addr, password, msg):
    '''
        send email in smtp
        use socket
    '''
    clientSocket = connect(smtp_server, 25)
    # list the way to connect
    cmd = 'ehlo 163.com'
    send(clientSocket, cmd)
    # use auth plain to connect
    auth = '\x00%s\x00%s' % (from_addr, password)
    pas = base64.b64encode(auth)
    cmd = 'AUTH PLAIN %s' % pas
    send(clientSocket, cmd)
    cmd = 'MAIL FROM:<%s>' % from_addr
    send(clientSocket, cmd)
    cmd = 'RCPT TO:<%s>' % to_addr
    send(clientSocket, cmd)
    cmd = 'data'
    send(clientSocket, cmd)
    cmd = str(msg) + '\r\n.'
    send(clientSocket, cmd)
    cmd = 'quit'
    send(clientSocket, cmd)

# api to get email use socket module
def get_email(email, password, pop3_server):
    '''
        get email in pop3
        use socket
        list last 10 emails
    '''
    clientSocket = connect(pop3_server, 110)
    cmd = 'USER %s' % email
    send(clientSocket, cmd)
    cmd = 'PASS %s' % password
    send(clientSocket, cmd)
    cmd = 'STAT'
    state = send(clientSocket, cmd)
    for i in re.findall(r"OK (.+?) ",state):
        length = int(i)
    for i in range(0,1):
        cmd = 'RETR %d' % (int(length)-i)
        mail = send(clientSocket, cmd)
        if len("".join(mail)) < 20:
            mail = clientSocket.recv(1024).decode('utf-8')
        m = re.findall(r"(\+OK.+?\r\n)",mail)
        a = len("".join(m))
        mail = mail[a:]
        print mail
        mail = Parser().parsestr(mail)
        print_info(mail)

    cmd = 'QUIT'
    send(clientSocket, cmd)
    '''
    cmd = 'QUIT'
    send(clientSocket, cmd)
    '''

# api to get email use pop3lib module
def get_email_with_lib(email, password, pop3_server):
    server = poplib.POP3(pop3_server)
    #server.set_debuglevel(1)
    print(server.getwelcome())
    server.user(email)
    server.pass_(password)
    print('Messages: %s. Size: %s' % server.stat())
    resp, mails, octets = server.list()
    index = len(mails)
    resp, lines, octets = server.retr(index)
    print (resp,lines,octets)
    msg_content = '\r\n'.join(lines)
    msg = Parser().parsestr(msg_content)
    print_info(msg)
    server.quit()

# api for gui to send email
def send_gui(from_addr, to_addr, password, subject, content):
    # use email lib to format MIME TYPE
    msg = MIMEText(content, 'plain', 'utf-8')
    msg['From'] = _format_addr(u'发件人<%s>' % from_addr)
    msg['To'] = _format_addr(u'收件人<%s>' % to_addr)
    msg['Subject'] = Header(subject, 'utf-8').encode()

    if re.findall(r"@(.+?).com",from_addr) == ["163"]:
        smtp_server = "smtp.163.com"

    send_email(smtp_server, from_addr, to_addr, password, msg)

# api for gui to get email
def get_gui(email, password):
    if re.findall(r"@(.+?).com",email) == ["163"]:
        pop3_server = "pop3.163.com"
    get_email(email, password, pop3_server)

def main():
    '''
    from_addr = raw_input('From: ')
    password = raw_input('Password: ')
    to_addr = raw_input('To: ')
    if re.findall(r"@(.+?).com",from_addr) == ["163"]:
        smtp_server = "smtp.163.com"

    # use email lib to format MIME TYPE
    msg = MIMEText('hello, send by Python...', 'plain', 'utf-8')
    msg['From'] = _format_addr(u'亦可赛艇<%s>' % from_addr)
    msg['To'] = _format_addr(u'本人<%s>' % to_addr)
    msg['Subject'] = Header(u'你好的问候……', 'utf-8').encode()

    #send_email_with_lib(smtp_server, from_addr, to_addr, password, msg)
    send_email(smtp_server, from_addr, to_addr, password, msg)
    '''
    email = raw_input('Email: ')
    password = raw_input('Password: ')
    pop3_server = raw_input('POP3 server: ')

    get_email(email, password, pop3_server)
    #get_email_with_lib(email, password, pop3_server)


if __name__ == '__main__':
    main()



